05. NumPy 中的元素级运算
元素级运算
Python 中的方式
假设你有一个数字列表,你想向列表中的每一项加上 5
。如果没有 NumPy,你可以像下面这样做:
values = [1,2,3,4,5]
for i in range(len(values)):
values[i] += 5
# 现在的 values 为 [6,7,8,9,10]
这是讲得通的,但是你要编写很多代码,而且因为它是纯 Python,所以运行的很慢。
注意: 如果你不习惯使用像 +=
这样的运算符,它的意思是"将两者相加,然后将结果保存在左边的项中"。这是 values[i] = values[i] + 5
的简便写法。你在这些示例中看到的代码会尽可能地使用此类运算符。
NumPy 中的方式
在 NumPy 中,我们可以这么做:
values = [1,2,3,4,5]
values = np.array(values) + 5
# 现在 values 是包含 [6,7,8,9,10] 的一个 ndarray
创建该数组可能看起来很奇怪,但通常你总是要将数据存储在 ndarray
中的。所以如果你已经有一个名为 values
的 ndarray
,你可以这么做:
values += 5
我们应该指出,NumPy 实际上有用于加法、乘法等运算的函数。但它也支持使用标准的数学运算符。所以以下两行是等价的:
x = np.multiply(some_array, 5)
x = some_array * 5
我们通常会使用运算符而不是函数,因为它们更方便键入,也更容易阅读,不过这只是个人偏好。
再看一个使用标量和 ndarrays
进行运算的例子。假设你有一个矩阵 m
并且你想复用它,但首先你需要将其所有值设为零。这很简单,只需给它乘以零,并将结果赋值回原矩阵就行了,如下所示:
m *= 0
# 现在 m 中的每个元素都是 0,无论它有多少维度
元素级矩阵运算
与标量和矩阵一起使用的相同函数和运算符也适用于其他维度。你只需要确保执行运算的项目具有兼容的形状。
假设你想得到矩阵的平方值。方法是 x = m * m
(或者如果你要将值赋值回 m
,则是 m *= m
)
这是可行的,因为它是两个形状相同的矩阵之间的元素乘法。(在这个例子中,它们的形状相同,是因为它们实际上是同一个对象。)
看看视频中的一个示例:
a = np.array([[1,3],[5,7]])
a
# 显示以下结果:
# array([[1, 3],
# [5, 7]])
b = np.array([[2,4],[6,8]])
b
# 显示以下结果:
# array([[2, 4],
# [6, 8]])
a + b
# 显示以下结果:
# array([[ 3, 7],
# [11, 15]])
如果你尝试使用不兼容的形状,就像视频中的另一个示例一样,你会收到一个错误:
a = np.array([[1,3],[5,7]])
a
# 显示以下结果:
# array([[1, 3],
# [5, 7]])
c = np.array([[2,3,6],[4,5,9],[1,8,7]])
c
# 显示以下结果:
# array([[2, 3, 6],
# [4, 5, 9],
# [1, 8, 7]])
a.shape
# 显示以下结果:
# (2, 2)
c.shape
# 显示以下结果:
# (3, 3)
a + c
# 显示以下结果:
# ValueError: operands could not be broadcast together with shapes (2,2) (3,3)
你会在后面的课程中详细了解“不能一起广播”的意义,现在只需注意这两种形状是不同的,因此我们无法执行元素级运算。